#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file api_client.py
@brief API客户端
@details 提供API客户端接口，供前端界面调用
@author zhang33
@date 2025-09-05
"""

import requests
import logging
from typing import Optional, Dict, Any, Callable
from enum import Enum

from core.logging_config import get_logger

logger = get_logger(__name__)


class ConnectionState(Enum):
    """连接状态枚举"""
    DISCONNECTED = "disconnected"
    CONNECTING = "connecting"
    CONNECTED = "connected"
    ERROR = "error"


class APIClient:
    """
    @brief API客户端类
    @details 提供API客户端接口，供前端界面调用
    """
    
    def __init__(self, base_url: str = "http://localhost:5000"):
        """
        @brief 初始化API客户端
        @param base_url API服务器基础URL
        """
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        self.session.timeout = 5.0  # 5秒超时
        
        # 回调函数
        self.connection_callback: Optional[Callable] = None
        self.status_callback: Optional[Callable] = None
        self.error_callback: Optional[Callable] = None
        
        logger.info(f"API客户端初始化完成 - 服务器地址: {self.base_url}")
    
    def set_connection_callback(self, callback: Callable) -> None:
        """
        @brief 设置连接状态回调
        @param callback 回调函数
        """
        self.connection_callback = callback
    
    def set_status_callback(self, callback: Callable) -> None:
        """
        @brief 设置状态回调
        @param callback 回调函数
        """
        self.status_callback = callback
    
    def set_error_callback(self, callback: Callable) -> None:
        """
        @brief 设置错误回调
        @param callback 回调函数
        """
        self.error_callback = callback
    
    def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None) -> Optional[Dict[str, Any]]:
        """
        @brief 发送HTTP请求
        @param method HTTP方法
        @param endpoint API端点
        @param data 请求数据
        @return Optional[Dict[str, Any]] 响应数据
        """
        try:
            url = f"{self.base_url}{endpoint}"
            logger.debug(f"发送HTTP请求: {method} {url}")
            
            if data:
                logger.debug(f"请求数据: {data}")
            
            response = self.session.request(method, url, json=data)
            response.raise_for_status()
            
            result = response.json()
            logger.debug(f"响应数据: {result}")
            
            return result
            
        except requests.exceptions.ConnectionError as e:
            error_msg = f"连接API服务器失败: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return None
            
        except requests.exceptions.Timeout as e:
            error_msg = f"API请求超时: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return None
            
        except requests.exceptions.HTTPError as e:
            error_msg = f"HTTP错误: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return None
            
        except Exception as e:
            error_msg = f"API请求异常: {e}"
            logger.error(error_msg)
            if self.error_callback:
                self.error_callback(error_msg)
            return None
    
    # ==================== 连接管理 ====================
    
    def connect(self) -> bool:
        """
        @brief 连接到电机驱动器
        @return bool 连接是否成功
        """
        logger.info("通过API连接电机驱动器")
        
        if self.connection_callback:
            self.connection_callback(ConnectionState.CONNECTING)
        
        result = self._make_request('POST', '/api/connect')
        
        if result and result.get('success'):
            logger.info("API连接成功")
            if self.connection_callback:
                self.connection_callback(ConnectionState.CONNECTED)
            return True
        else:
            logger.error("API连接失败")
            if self.connection_callback:
                self.connection_callback(ConnectionState.ERROR)
            return False
    
    def disconnect(self) -> bool:
        """
        @brief 断开连接
        @return bool 断开是否成功
        """
        logger.info("通过API断开连接")
        
        result = self._make_request('POST', '/api/disconnect')
        
        if result and result.get('success'):
            logger.info("API断开连接成功")
            if self.connection_callback:
                self.connection_callback(ConnectionState.DISCONNECTED)
            return True
        else:
            logger.error("API断开连接失败")
            return False
    
    def is_connected(self) -> bool:
        """
        @brief 检查是否已连接
        @return bool 是否已连接
        """
        result = self._make_request('GET', '/api/status')
        return result.get('connected', False) if result else False
    
    def test_connection(self) -> bool:
        """
        @brief 测试连接
        @return bool 连接是否正常
        """
        logger.info("通过API测试连接")
        
        result = self._make_request('GET', '/api/test')
        return result.get('success', False) if result else False
    
    # ==================== 电机控制 ====================
    
    def start_motors(self, left_speed: int = 500, right_speed: int = 500) -> bool:
        """
        @brief 启动电机
        @param left_speed 左电机转速
        @param right_speed 右电机转速
        @return bool 启动是否成功
        """
        logger.info(f"通过API启动电机 - 左电机: {left_speed}, 右电机: {right_speed}")
        
        data = {
            'left_speed': left_speed,
            'right_speed': right_speed
        }
        
        result = self._make_request('POST', '/api/motor/start', data)
        return result.get('success', False) if result else False
    
    def stop_motors(self) -> bool:
        """
        @brief 停止电机
        @return bool 停止是否成功
        """
        logger.info("通过API停止电机")
        
        result = self._make_request('POST', '/api/motor/stop')
        return result.get('success', False) if result else False
    
    def emergency_stop(self) -> bool:
        """
        @brief 急停电机
        @return bool 急停是否成功
        """
        logger.warning("通过API急停电机")
        
        result = self._make_request('POST', '/api/motor/emergency_stop')
        return result.get('success', False) if result else False
    
    def set_motor_speed(self, left_speed: Optional[int] = None, 
                       right_speed: Optional[int] = None) -> bool:
        """
        @brief 设置电机转速
        @param left_speed 左电机转速
        @param right_speed 右电机转速
        @return bool 设置是否成功
        """
        logger.info(f"通过API设置电机转速 - 左电机: {left_speed}, 右电机: {right_speed}")
        
        data = {}
        if left_speed is not None:
            data['left_speed'] = left_speed
        if right_speed is not None:
            data['right_speed'] = right_speed
        
        result = self._make_request('POST', '/api/motor/speed', data)
        return result.get('success', False) if result else False
    
    def phase_learning(self) -> bool:
        """
        @brief 执行相序学习
        @return bool 相序学习是否成功
        """
        logger.info("通过API执行相序学习")
        
        result = self._make_request('POST', '/api/motor/phase_learning')
        return result.get('success', False) if result else False
    
    def reset_system(self) -> bool:
        """
        @brief 复位系统
        @return bool 复位是否成功
        """
        logger.info("通过API复位系统")
        
        result = self._make_request('POST', '/api/motor/reset')
        return result.get('success', False) if result else False
    
    # ==================== 便捷控制 ====================
    
    def move_forward(self, speed: int = 500) -> bool:
        """
        @brief 前进
        @param speed 转速
        @return bool 操作是否成功
        """
        logger.info(f"通过API前进 - 转速: {speed}")
        
        data = {'speed': speed}
        result = self._make_request('POST', '/api/motor/forward', data)
        return result.get('success', False) if result else False
    
    def move_backward(self, speed: int = 500) -> bool:
        """
        @brief 后退
        @param speed 转速
        @return bool 操作是否成功
        """
        logger.info(f"通过API后退 - 转速: {speed}")
        
        data = {'speed': speed}
        result = self._make_request('POST', '/api/motor/backward', data)
        return result.get('success', False) if result else False
    
    def turn_left(self, speed: int = 500) -> bool:
        """
        @brief 左转
        @param speed 转速
        @return bool 操作是否成功
        """
        logger.info(f"通过API左转 - 转速: {speed}")
        
        data = {'speed': speed}
        result = self._make_request('POST', '/api/motor/turn_left', data)
        return result.get('success', False) if result else False
    
    def turn_right(self, speed: int = 500) -> bool:
        """
        @brief 右转
        @param speed 转速
        @return bool 操作是否成功
        """
        logger.info(f"通过API右转 - 转速: {speed}")
        
        data = {'speed': speed}
        result = self._make_request('POST', '/api/motor/turn_right', data)
        return result.get('success', False) if result else False
    
    def differential_move(self, left_speed: int, right_speed: int) -> bool:
        """
        @brief 差速移动
        @param left_speed 左电机转速
        @param right_speed 右电机转速
        @return bool 操作是否成功
        """
        logger.info(f"通过API差速移动 - 左电机: {left_speed}, 右电机: {right_speed}")
        
        data = {
            'left_speed': left_speed,
            'right_speed': right_speed
        }
        result = self._make_request('POST', '/api/motor/differential', data)
        return result.get('success', False) if result else False
    
    # ==================== 状态监控 ====================
    
    def get_motor_status(self) -> Optional[Dict[str, Any]]:
        """
        @brief 获取电机状态
        @return Optional[Dict[str, Any]] 电机状态信息
        """
        result = self._make_request('GET', '/api/status')
        return result.get('motor_status') if result else None
    
    def start_monitoring(self) -> bool:
        """
        @brief 开始状态监控
        @return bool 启动是否成功
        """
        logger.info("通过API开始状态监控")
        
        result = self._make_request('POST', '/api/monitor/start')
        return result.get('success', False) if result else False
    
    def stop_monitoring(self) -> bool:
        """
        @brief 停止状态监控
        @return bool 停止是否成功
        """
        logger.info("通过API停止状态监控")
        
        result = self._make_request('POST', '/api/monitor/stop')
        return result.get('success', False) if result else False
    
    def is_monitoring(self) -> bool:
        """
        @brief 检查是否正在监控
        @return bool 是否正在监控
        """
        result = self._make_request('GET', '/api/monitor/status')
        return result.get('monitoring', False) if result else False
    
    # ==================== 数据记录 ====================
    
    def start_logging(self, log_file: str = "motor_data.log") -> bool:
        """
        @brief 开始数据记录
        @param log_file 日志文件路径
        @return bool 启动是否成功
        """
        logger.info(f"通过API开始数据记录 - 日志文件: {log_file}")
        
        data = {'log_file': log_file}
        result = self._make_request('POST', '/api/log/start', data)
        return result.get('success', False) if result else False
    
    def stop_logging(self) -> bool:
        """
        @brief 停止数据记录
        @return bool 停止是否成功
        """
        logger.info("通过API停止数据记录")
        
        result = self._make_request('POST', '/api/log/stop')
        return result.get('success', False) if result else False
    
    def is_logging(self) -> bool:
        """
        @brief 检查是否正在记录
        @return bool 是否正在记录
        """
        result = self._make_request('GET', '/api/log/status')
        return result.get('logging', False) if result else False
    
    # ==================== 配置管理 ====================
    
    def get_serial_config(self) -> Optional[Dict[str, Any]]:
        """
        @brief 获取串口配置
        @return Optional[Dict[str, Any]] 串口配置信息
        """
        result = self._make_request('GET', '/api/config/serial')
        return result.get('config') if result else None
    
    def set_serial_config(self, config: Dict[str, Any]) -> bool:
        """
        @brief 设置串口配置
        @param config 串口配置字典
        @return bool 设置是否成功
        """
        logger.info(f"通过API设置串口配置: {config}")
        
        result = self._make_request('POST', '/api/config/serial', config)
        return result.get('success', False) if result else False
    
    def get_motor_config(self) -> Optional[Dict[str, Any]]:
        """
        @brief 获取电机配置
        @return Optional[Dict[str, Any]] 电机配置信息
        """
        result = self._make_request('GET', '/api/config/motor')
        return result.get('config') if result else None
    
    def set_motor_config(self, config: Dict[str, Any]) -> bool:
        """
        @brief 设置电机配置
        @param config 电机配置字典
        @return bool 设置是否成功
        """
        logger.info(f"通过API设置电机配置: {config}")
        
        result = self._make_request('POST', '/api/config/motor', config)
        return result.get('success', False) if result else False
    
    def save_config(self) -> bool:
        """
        @brief 保存配置
        @return bool 保存是否成功
        """
        logger.info("通过API保存配置")
        
        result = self._make_request('POST', '/api/config/save')
        return result.get('success', False) if result else False
    
    def load_config(self) -> bool:
        """
        @brief 加载配置
        @return bool 加载是否成功
        """
        logger.info("通过API加载配置")
        
        result = self._make_request('POST', '/api/config/load')
        return result.get('success', False) if result else False
    
    # ==================== 健康检查 ====================
    
    def health_check(self) -> Optional[Dict[str, Any]]:
        """
        @brief 健康检查
        @return Optional[Dict[str, Any]] 健康状态信息
        """
        result = self._make_request('GET', '/api/health')
        return result if result else None
